#ifndef _NAND_W25N_H
#define _NAND_W25N_H

#include "nand_spi.h"

/*****************************************************************************
* @brief   STATUS
*****************************************************************************/
#define NAND_FEATURE_1_PROTECT            0xA0  //Ax
#define NAND_FEATURE_2_CFG                0xB0  //Bx  
#define NAND_FEATURE_3_ST                 0xC0  //Cx

#define NAND_ST_BUSY_MASK				  0x01
#define NAND_ST_WREN_MASK				  0x02
#define NAND_ST_ECC_MASK				  0x30
/*****************************************************************************
* @brief   STRUCT
*****************************************************************************/
typedef struct
{
	uint16_t page_main_size;
	uint16_t page_spare_size;
	uint16_t page_per_block;
	uint16_t block_total;
	uint8_t dev_st;				//busy 等待时，FEATURE_3_ST 读取值
	uint8_t	ecc_err;
} nand_info_type;

extern nand_info_type spi_nand_info;

/*****************************************************************************
* @brief   NAND-FLASH COMMON API
*****************************************************************************/
void spi_nand_reset(void);

uint8_t spi_nand_featute_get(uint8_t reg_addr);
uint8_t spi_nand_featute_set(uint8_t reg_addr, uint8_t msk, uint8_t dat);

uint8_t spi_nand_wait_ready(void);

uint8_t spi_nand_ecc_error_get(void);

uint8_t spi_nand_write_enable(void);
uint8_t spi_nand_write_disable(void);

void spi_nand_read_id(uint8_t *dat);

/* read and write */
uint8_t spi_nand_read_page(uint32_t page_addr);

uint8_t spi_nand_read_cache(uint16_t coil_addr, uint8_t * dat, uint16_t Len);
uint8_t spi_nand_q_read_cache(uint16_t coil_addr, uint8_t * dat, uint16_t Len);

uint8_t spi_nand_write_cache(uint16_t coil_addr, const uint8_t * dat, uint16_t Len);	// clear cache and write dat 
uint8_t spi_nand_random_write_cache(uint16_t addr, const uint8_t * dat, uint16_t Len);	// keep cache and write dat
uint8_t spi_nand_q_write_cache(uint16_t coil_addr, const uint8_t * dat, uint16_t Len);
uint8_t spi_nand_q_random_write_cache(uint16_t addr, const uint8_t * dat, uint16_t Len);

uint8_t spi_nand_program_exe(uint32_t page_addr);

/* erase */
uint8_t spi_nand_block_erase(uint32_t block_addr);
uint8_t spi_nand_chip_erase(void);
uint8_t spi_nand_block_empty_check(uint32_t block_addr); // 需malloc支持

/* auto cmd */
void spi_nand_cmd_exe(uint8_t cmd);
void spi_nand_cmd_set(uint8_t cmd, uint8_t par);
uint8_t spi_nand_cmd_get(uint8_t cmd);
uint8_t spi_nand_cmd_auto(const uint8_t *send, uint8_t send_len, uint8_t *rcv, uint8_t rcv_cnt);

/*****************************************************************************
* @brief   SPECIAL API for W25N
*****************************************************************************/
uint8_t w25n_opt_mem_select(void);
uint8_t w25n_main_mem_select(void);
uint8_t w25n_init(void);

/*****************************************************************************
* @brief   SPECIAL API for GD5
*****************************************************************************/
uint8_t gd5_opt_mem_select(void);
uint8_t gd5_main_mem_select(void);
uint8_t gd5_init(void);

#endif
